---
title: 图片
icon: ImagePlus
---

<MetaData
  lang="zh-CN"
  meta={{
    preset: [{
      client: '@univerjs/preset-sheets-drawing',
      locale: '@univerjs/preset-sheets-drawing/locales/zh-CN',
      style: '@univerjs/preset-sheets-drawing/lib/index.css',
    }],
    plugins: [{
      client: '@univerjs/drawing',
    }, {
      client: '@univerjs/drawing-ui',
      locale: '@univerjs/drawing-ui/locale/zh-CN',
      style: '@univerjs/drawing-ui/lib/index.css',
    }, {
      client: '@univerjs/sheets-drawing',
    }, {
      client: '@univerjs/sheets-drawing-ui',
      facade: '@univerjs/sheets-drawing-ui/facade',
      locale: '@univerjs/sheets-drawing-ui/locale/zh-CN',
      style: '@univerjs/sheets-drawing-ui/lib/index.css',
    }],
    server: '否',
  }}
/>

图片功能允许用户在电子表格中插入和管理图片，以便更好地展示数据和信息。它支持多种图片格式和操作，帮助用户创建更丰富的文档。

目前支持插入的图片类型为：浮动图片、单元格图片

<PlaygroundFrame lang="zh-CN" slug="sheets/images" clickToShow />

## 预设模式

### 安装

```package-install
npm install @univerjs/preset-sheets-drawing
```

### 使用

```typescript
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core'
import UniverPresetSheetsCoreZhCN from '@univerjs/preset-sheets-core/locales/zh-CN'
import { UniverSheetsDrawingPreset } from '@univerjs/preset-sheets-drawing' // [!code ++]
import UniverPresetSheetsDrawingZhCN from '@univerjs/preset-sheets-drawing/locales/zh-CN' // [!code ++]
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets'

import '@univerjs/preset-sheets-core/lib/index.css'
import '@univerjs/preset-sheets-drawing/lib/index.css' // [!code ++]

const { univerAPI } = createUniver({
  locale: LocaleType.ZH_CN,
  locales: {
    [LocaleType.ZH_CN]: mergeLocales(
      UniverPresetSheetsCoreZhCN,
      UniverPresetSheetsDrawingZhCN, // [!code ++]
    ),
  },
  presets: [
    UniverSheetsCorePreset(),
    UniverSheetsDrawingPreset(), // [!code ++]
  ],
})
```

如使用[协同编辑](/guides/sheets/features/collaboration)功能，请确保在 `UniverSheetsDrawingPreset` 中传入 `collaboration: true` 选项。

```typescript
UniverSheetsDrawingPreset({
  collaboration: true, // [!code ++]
})
```

{/* ### 预设与配置 */}

## 插件模式

### 安装

```package-install
npm install @univerjs/docs-drawing @univerjs/drawing @univerjs/drawing-ui @univerjs/sheets-drawing @univerjs/sheets-drawing-ui
```

### 使用

```typescript
import { LocaleType, mergeLocales, Univer } from '@univerjs/core'
import { UniverDocsDrawingPlugin } from '@univerjs/docs-drawing' // [!code ++]
import { IImageIoService, UniverDrawingPlugin } from '@univerjs/drawing' // [!code ++]
import { UniverDrawingUIPlugin } from '@univerjs/drawing-ui' // [!code ++]
import DrawingUIZhCN from '@univerjs/drawing-ui/locale/zh-CN' // [!code ++]
import { UniverSheetsDrawingPlugin } from '@univerjs/sheets-drawing' // [!code ++]
import { UniverSheetsDrawingUIPlugin } from '@univerjs/sheets-drawing-ui' // [!code ++]
import SheetsDrawingUIZhCN from '@univerjs/sheets-drawing-ui/locale/zh-CN' // [!code ++]

import '@univerjs/drawing-ui/lib/index.css' // [!code ++]
import '@univerjs/sheets-drawing-ui/lib/index.css' // [!code ++]

import '@univerjs/sheets-drawing-ui/facade' // [!code ++]

const univer = new Univer({
  locale: LocaleType.ZH_CN,
  locales: {
    [LocaleType.ZH_CN]: mergeLocales(
      DrawingUIZhCN, // [!code ++]
      SheetsDrawingUIZhCN, // [!code ++]
    ),
  },
})

univer.registerPlugin(UniverSheetsFilterPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsFilterUIPlugin) // [!code ++]

univer.registerPlugin(UniverDrawingPlugin) // [!code ++]
univer.registerPlugin(UniverDrawingUIPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsDrawingPlugin) // [!code ++]
univer.registerPlugin(UniverSheetsDrawingUIPlugin) // [!code ++]
```

如使用[协同编辑](/guides/docs/features/collaboration)功能，需要添加 `override` 配置：

```typescript
univer.registerPlugin(UniverDrawingPlugin, {
  override: [[IImageIoService, null]], // [!code ++]
})
```

{/* ### 插件与配置 */}

## Facade API

完整 Facade API 类型定义，请查看 [FacadeAPI](https://reference.univer.ai/zh-CN)。

### 添加浮动 DOM

`FWorksheet.addFloatDomToPosition(layer)` 方法可以添加一个浮动的 DOM 元素到指定位置。

```tsx
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()

// 你应该在合适的时机注册组件（例如 Univer 加载完成时）
// 这是一个 React 组件。对于 Vue3 组件，第三个参数应该是 `{ framework: 'vue3' }`
univerAPI.registerComponent(
  'myFloatDom',
  ({ data }) => (
    <div style={{ width: '100%', height: '100%', background: '#fff', border: '1px solid #ccc', boxSizing: 'border-box' }}>
      popup content:
      {' '}
      {data?.label}
    </div>
  ),
)

// 添加浮动 DOM
// 如果 disposable 为 null，则浮动 DOM 添加失败
const disposable = fWorksheet.addFloatDomToPosition({
  componentKey: 'myFloatDom',
  initPosition: {
    startX: 100,
    endX: 300,
    startY: 100,
    endY: 200,
  },

  // 组件数据
  data: {
    label: 'hahah',
  },
})

// 2 秒后移除浮动 DOM
setTimeout(() => {
  disposable?.dispose()
}, 2000)
```

`FWorksheet.addFloatDomToRange(range, layer, domLayout)` 方法可以添加一个浮动的 DOM 元素到指定范围。

```tsx
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()

// 注册一个范围加载组件
function RangeLoading() {
  const divStyle = {
    width: '100%',
    height: '100%',
    backgroundColor: '#fff',
    border: '1px solid #ccc',
    boxSizing: 'border-box' as const,
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    textAlign: 'center' as const,
    transformOrigin: 'top left',
  }

  return (
    <div style={divStyle}>
      Loading...
    </div>
  )
}
univerAPI.registerComponent('RangeLoading', RangeLoading)

// 添加范围加载组件覆盖范围 A1:C3
const fRange = fWorksheet.getRange('A1:C3')
const disposable = fWorksheet.addFloatDomToRange(fRange, { componentKey: 'RangeLoading' }, {}, 'myRangeLoading')

// 2 秒后移除浮动 DOM
setTimeout(() => {
  disposable?.dispose()
}, 2000)

// 另外一个示例 -------------------
// 注册一个浮动按钮组件
function FloatButton() {
  const divStyle = {
    width: '100px',
    height: '30px',
    backgroundColor: '#fff',
    border: '1px solid #ccc',
    boxSizing: 'border-box' as const,
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    textAlign: 'center' as const,
    cursor: 'pointer',
  }

  const clickHandler = () => {
    console.warn('click')
  }

  return (
    <div style={divStyle} onClick={clickHandler}>
      FloatButton
    </div>
  )
}
univerAPI.registerComponent('FloatButton', FloatButton)

// 添加浮动按钮到范围 A5:C7，位置从 A5 单元格开始，宽度为 100px，高度为 30px，边距为范围宽度和高度的 100%
const fRange2 = fWorksheet.getRange('A5:C7')
const disposable2 = fWorksheet.addFloatDomToRange(
  fRange2,
  {
    componentKey: 'FloatButton',
  },
  {
    width: 100,
    height: 30,
    marginX: '100%', // 边距百分比到范围宽度，或像素
    marginY: '100%',
  },
  'myFloatButton',
)
```

`FWorksheet.addFloatDomToColumnHeader(column, layer, domPos)` 方法可以添加一个浮动的 DOM 元素到指定列头。

```tsx
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()

// 注册一个浮动按钮组件
function FloatButton() {
  const divStyle = {
    width: '100px',
    height: '30px',
    backgroundColor: '#fff',
    border: '1px solid #ccc',
    boxSizing: 'border-box' as const,
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    textAlign: 'center' as const,
    cursor: 'pointer',
  }

  const clickHandler = () => {
    console.warn('click')
  }

  return (
    <div style={divStyle} onClick={clickHandler}>
      FloatButton
    </div>
  )
}
univerAPI.registerComponent('FloatButton', FloatButton)

// 添加浮动按钮到列 D 头部，位置为右对齐，宽度为 100px，高度为 30px，边距为 0
const disposable = fWorksheet.addFloatDomToColumnHeader(
  3,
  {
    componentKey: 'FloatButton',
    allowTransform: false,
  },
  {
    width: 100,
    height: 30,
    marginX: 0,
    marginY: 0,
    horizonOffsetAlign: 'right',
  },
  'myFloatButton',
)

// 2 秒后移除浮动按钮
setTimeout(() => {
  disposable?.dispose()
}, 2000)
```

### 插入浮动图片

[`FWorksheet.newOverGridImage()`](https://reference.univer.ai/zh-CN/classes/FWorksheet#newovergridimage) 创建一个浮动图片构建器，返回一个 `FOverGridImageBuilder` 实例，可以通过链式调用生成 `ISheetImage` 对象用于插入浮动图片。

以下是 [`FOverGridImageBuilder`](https://reference.univer.ai/zh-CN/classes/FOverGridImageBuilder) 上的一些成员方法：

| 方法 | 描述 |
| ---- | ---- |
| buildAsync | 构建 `ISheetImage` 对象用于插入浮动图片 |
| setSource | 设置 image 的来源 |
| setColumn | 设置 image 的水平方向位置 |
| setRow | 设置 image 的垂直方向位置 |
| setColumnOffset | 设置 image 的水平方向偏移 |
| setRowOffset | 设置 image 的垂直方向偏移 |
| setWidth | 设置 image 的宽度 |
| setHeight | 设置 image 的高度 |
| setAnchorType | 设置 image 的锚点类型，是否随单元格位置和大小变化 |
| setCropTop | 设置 image 的裁剪区域，定义顶部边缘，从而显示您想要的图像的特定部分 |
| setCropLeft | 设置 image 的裁剪区域，定义左边缘，从而显示您想要的图像的特定部分 |
| setCropBottom | 设置 image 的裁剪区域，定义底部边缘，从而显示您想要的图像的特定部分 |
| setCropRight | 设置 image 的裁剪区域，定义右边缘，从而显示您想要的图像的特定部分 |
| setRotate | 设置 image 的旋转角度 |

```typescript
// 创建一个新的图片构建器并设置图片来源。
// 然后构建 `ISheetImage` 并插入到工作表中，位置从 F6 单元格开始，宽度为 500px，高度为 300px
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const image = await fWorksheet.newOverGridImage()
  .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
  .setColumn(5)
  .setRow(5)
  .setWidth(500)
  .setHeight(300)
  .buildAsync()
fWorksheet.insertImages([image])
```

亦可以通过 `FWorksheet.insertImage(url, column, row, offsetX, offsetY)` 方法插入图片。

```typescript
// 插入一个图片到工作表，位置为 F6，偏移为 10px
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()
const result = await fWorksheet.insertImage('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', 5, 5, 10, 10)
```

### 获取浮动图片

`FWorksheet.getImages()` 方法可以获取工作表中的所有浮动图片，返回一个 [`FOverGridImage[]`](https://reference.univer.ai/zh-CN/classes/FOverGridImage) 实例数组。

```typescript
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()
const images = fWorksheet.getImages()
images.forEach((image) => {
  image.getId()
})
```

亦可以通过 `FWorksheet.getImageById(id)` 方法获取指定 id 的浮动图片。

### 更新浮动图片

`FWorksheet.updateImages(sheetImages)` 方法可以更新浮动图片的位置和大小等属性。

```typescript
// 创建一个新的图片构建器并设置图片来源。
// 然后构建 `ISheetImage` 并插入到工作表中，位置从 F6 单元格开始，宽度为 500px，高度为 300px
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()
const image = await fWorksheet.newOverGridImage()
  .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
  .setColumn(5)
  .setRow(5)
  .setWidth(500)
  .setHeight(300)
  .buildAsync()
fWorksheet.insertImages([image])

// 4 秒后更新图片宽度为 100px，高度为 50px
setTimeout(async () => {
  const imageBuilder = fWorksheet.getImageById(image.drawingId).toBuilder()
  const newImage = await imageBuilder.setWidth(100).setHeight(50).buildAsync()
  fWorksheet.updateImages([newImage])
}, 4000)
```

### 删除浮动图片

`FWorksheet.deleteImages(sheetImages)` 方法可以删除浮动图片。

```typescript
const fWorksheet = univerAPI.getActiveWorkbook().getActiveSheet()
const image = fWorksheet.getImages()[0]

// 删除工作表中的第一个图片
fWorksheet.deleteImages([image])
```

### 插入单元格图片

`FRange.insertCellImageAsync(file)` 方法可以插入单元格图片。

```typescript
const fWorkbook = univerAPI.getActiveWorkbook()
const fWorksheet = fWorkbook.getActiveSheet()

// 在 A10 单元格插入一个图片
const fRange = fWorksheet.getRange('A10')
const result = await fRange.insertCellImageAsync('https://avatars.githubusercontent.com/u/61444807?s=48&v=4')
```
